package com._51cto.healthy.security;


import com._51cto.healthy.content.R;
import com.alibaba.fastjson.JSONObject;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.util.UUID;

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true) //开启授权注解
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    //配置密码加密策略
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    //把重写的过滤器方法注入到spring security中 ,交由spring security管理
    @Bean
    public SecurityUnPsAuthFilter unPsAuthFilter() throws Exception {
        SecurityUnPsAuthFilter authFilter = new SecurityUnPsAuthFilter();
        //设置 认证成功返回
        authFilter.setAuthenticationSuccessHandler((req, res, ex) -> {
            //设置返回结果为JSON-UTF8格式
            res.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
            //生成UUID，
            String token = UUID.randomUUID().toString();
            //获取session,将token和用户信息存入session
            req.getSession().setAttribute(token, ex.getPrincipal());
            //封装返回结果
            String result = JSONObject.toJSONString(R.success(token, "用户登录成功！"));
            //回写成功信息,返回给浏览器
            res.getWriter().write(result);
        });
        //设置 认证失败返回
        authFilter.setAuthenticationFailureHandler((req, res, ex) -> {
            //设置返回接过为JSON-UTF8
            res.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
            //封装返回结果
            String result = JSONObject.toJSONString(R.fail("用户名或密码错误！"));
            //回写失败信息.返回给浏览器
            res.getWriter().write(result);
        });
        //注入管理器
        authFilter.setAuthenticationManager(authenticationManager());
        return authFilter;
    }

    //基本配置 --放行静态资源(登录页面)
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //指定登录校验URL和登录页面地址
        http.formLogin().loginProcessingUrl("/login").loginPage("/#/login");
        //指定登出URL地址
        http.logout().logoutUrl("/logout").logoutSuccessHandler((req,resp,ex)->{
            //退出后设置用户session为无效
            req.getSession().invalidate();
            //设置JSON格式
            resp.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
            //使用JSON工具将对象转为JSON格式的字符串
            String result = JSONObject.toJSONString(R.success("用户登出成功！"));
            //回写登录信息,返回给浏览器
            resp.getWriter().write(result);
        });
        //设置--静态资源访问权限--所有静态资源皆可访问
        http.authorizeRequests().antMatchers("/", "/#/login", "/static/**", "/index.html").permitAll();
        //设置--校验用户名，登录地址--访问权限
        http.authorizeRequests().antMatchers("/valid-username", "/login").permitAll();
        //设置其他所有请求都需要认证
        http.authorizeRequests((requests) -> requests.anyRequest().authenticated());
        //关闭CORS跨域防护和CSRF跟踪
        http.cors().and().csrf().disable();
        //替换过滤器
        http.addFilterAt(unPsAuthFilter(),UsernamePasswordAuthenticationFilter.class);
    }
}
